package io.lkt.common.utils;

import org.apache.commons.lang3.StringUtils;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.openqa.selenium.phantomjs.PhantomJSDriver;
import org.openqa.selenium.phantomjs.PhantomJSDriverService;
import org.openqa.selenium.remote.DesiredCapabilities;
import org.springframework.util.CollectionUtils;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

public class PhantomjsUtil {
    /**
     * window 平台获取动态 js 页面
     *
     * 1、需要 phantomjs.exe 可执行文件
     *
     * 2、需要脚本自定义 parser.js
     *
     * @param url 链接
     * @return html 页面
     * @throws Exception
     */
    public static String handle(String url) throws Exception {
        Runtime rt = Runtime.getRuntime();
        Process process = null;
        try {
            process = rt.exec("D:/phantomjs/phantomjs.exe D:/phantomjs/parser.js " +url);
            InputStream in = process.getInputStream();
            InputStreamReader reader = new InputStreamReader(in, "UTF-8");
            BufferedReader br = new BufferedReader(reader);
            StringBuffer sbf = new StringBuffer();
            String tmp = "";
            while ((tmp = br.readLine()) != null) {
                sbf.append(tmp);
            }
            String finalContent = sbf.toString();
            System.out.println("success");
            return sbf.toString();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * linux 平台 - 获取浏览器对象
     * @param url 链接
     * @return 浏览器对象
     */
    public static PhantomJSDriver getBrowerObject(String url) {
        //设置必要参数
        DesiredCapabilities dcaps = new DesiredCapabilities();
        //ssl证书支持
        dcaps.setCapability("acceptSslCerts", true);
        //截屏支持
        dcaps.setCapability("takesScreenshot", true);
        //css搜索支持
        dcaps.setCapability("cssSelectorsEnabled", true);
        //js支持
        dcaps.setJavascriptEnabled(true);
        //驱动支持（第二参数表明的是你的phantomjs引擎所在的路径）
        dcaps.setCapability(PhantomJSDriverService.PHANTOMJS_EXECUTABLE_PATH_PROPERTY, "/usr/bin/phantomjs");
        //创建无界面浏览器对象
        PhantomJSDriver driver = new PhantomJSDriver(dcaps);

        //设置隐性等待（作用于全局）
        driver.manage().timeouts().implicitlyWait(5, TimeUnit.SECONDS);
        driver.manage().timeouts().pageLoadTimeout(10, TimeUnit.SECONDS);
        driver.manage().timeouts().setScriptTimeout(10, TimeUnit.SECONDS);

        //打开页面
        driver.get(url);

        return driver;
    }

    /**
     * 利用 PhantomJS 工具爬取 html 页面
     * @param url 链接地址
     * @return html 页面文本
     * @throws Exception
     */
    public static String getPageSource(String url) {
        // html 页面
        String pageSource = "";
        //设置必要参数
        DesiredCapabilities dcaps = new DesiredCapabilities();
        //ssl证书支持
        dcaps.setCapability("acceptSslCerts", true);
        //截屏支持
        dcaps.setCapability("takesScreenshot", true);
        //css搜索支持
        dcaps.setCapability("cssSelectorsEnabled", true);
        //js支持
        dcaps.setJavascriptEnabled(true);
        //驱动支持（第二参数表明的是你的phantomjs引擎所在的路径）
        dcaps.setCapability(PhantomJSDriverService.PHANTOMJS_EXECUTABLE_PATH_PROPERTY, "/usr/bin/phantomjs");

        PhantomJSDriver driver = null;
        try {
            //创建无界面浏览器对象
            driver = new PhantomJSDriver(dcaps);

            //设置隐性等待（作用于全局）
            driver.manage().timeouts().implicitlyWait(5, TimeUnit.SECONDS);
//            driver.manage().timeouts().pageLoadTimeout(10, TimeUnit.SECONDS);
//            driver.manage().timeouts().setScriptTimeout(10, TimeUnit.SECONDS);

            //打开页面
            driver.get(url);
            Thread.sleep(5000);
            pageSource = driver.getPageSource();
        } catch (Exception e) {

        } finally {
            if (driver != null) {
                driver.quit();// 退出
            }
        }
        return pageSource;
    }

    /**
     * 解析动态 js 页面的视频链接
     * @param weiXinPageUrl 微信链接地址
     * @return html
     */
    public static List<String> parseVideo(String weiXinPageUrl) {
        final String videoElementPrefixName = "<video";// video 标签前缀
        final String iframeElementPrefixName = "<iframe";// iframe 标签前缀

        List<String> videoLinkList = new ArrayList<>();// 最终结果
        List<Map<String, Object>> videoSource = new ArrayList<>();// 主要用于视频排序

        String pageSource = getPageSource(weiXinPageUrl);
        Document document = Jsoup.parse(pageSource);// 解析文本
        Element content = document.select("div#js_content").first();// 解析文本

        if (content != null) {
            // 第一步：解析 video 标签
            int videoOffset = 0;
            Elements videoElements = content.select("video");// video 标签
            if (!videoElements.isEmpty()) {
                for (Element videoElement : videoElements) {
                    String src = videoElement.attr("src");// src 属性
                    if (StringUtils.isNotBlank(src)) {
                        int index = pageSource.indexOf(videoElementPrefixName, videoOffset);// video 元素的位置

                        Map<String, Object> videoOptions = new HashMap<>();
                        videoOptions.put("index", Integer.valueOf(index));
                        videoOptions.put("src", src.startsWith("//") ? "https:" + src : src);// 以 // 开头的链接，加上 https: 协议头

                        videoSource.add(videoOptions);

                        videoOffset = index + videoElementPrefixName.length();// 偏移量增加
                    }
                }
            }

            // 第二步：解析 iframe 标签
            int iframeOffset = 0;
            Elements iframeElements = content.select("iframe");// iframe 标签
            if (!iframeElements.isEmpty()) {
                for (Element iframeElement : iframeElements) {
                    String src = iframeElement.attr("src");// src 属性
                    if (StringUtils.isNotBlank(src)) {
                        int index = pageSource.indexOf(iframeElementPrefixName, iframeOffset);// iframe 元素的位置

                        Map<String, Object> iframeOptions = new HashMap<>();
                        iframeOptions.put("index", Integer.valueOf(index));
                        iframeOptions.put("src", src.startsWith("//") ? "https:" + src : src);// 以 // 开头的链接，加上 https: 协议头

                        videoSource.add(iframeOptions);

                        iframeOffset = index + iframeElementPrefixName.length();// 偏移量增加
                    }
                }
            }

            // 第三步：对结果集排序
            if (!CollectionUtils.isEmpty(videoSource) && videoSource.size() > 0) {
                videoSource.stream().sorted(Comparator.comparing(PhantomjsUtil::getIndexValueInMap)).collect(Collectors.toList())
                        .forEach(info -> {
                            videoLinkList.add(info.get("src").toString());// 存入集合
                        });
            }
        }

        return videoLinkList;
    }

    // 用于 List<Map<String, Object>> 排序
    public static Integer getIndexValueInMap(Map<String, Object> map) {
        return (Integer) map.get("index");
    }
}
